package br.ufpe.cin.rdfilter.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import br.ufpe.cin.rdfilter.feedback.Annotation;
import br.ufpe.cin.rdfilter.feedback.Feedback;
import br.ufpe.cin.rdfilter.feedback.Triple;

public class LoadFeedback {

	private List<Feedback> feedbackList = new ArrayList<Feedback>();
	private File dir;
	private List<Annotation> annotation = new ArrayList<Annotation>();

	public LoadFeedback(){
		
	}
	public LoadFeedback(File dir) {
		this.dir = dir;
	}

	public File getDir() {
		return dir;
	}

	public void setDir(File dir) {
		this.dir = dir;
	}

	public List<Annotation> getAnnotation() {
		return annotation;
	}

	public void setAnnotation(ArrayList<Annotation> annotation) {
		this.annotation = annotation;
	}
	
	public List<Feedback> loadAll(List<String> queries){
		for (int i=0;i<queries.size();i++){
			feedbackList.add(this.load(queries.get(i)));
		}
		return feedbackList;
	}

	public Feedback load(String query) {
		Feedback f=null;
		try {
			
			FileReader reader = new FileReader("notes.txt");
			BufferedReader in = new BufferedReader(reader);
			String line = null;
			String[] result = null;
			// List<Annotation> annotation = new ArrayList<Annotation>();
			Annotation annot = null;
			List<String> tokens;
			List<String> terms;

			while ((line = in.readLine()) != null) {
				annot = new Annotation();
				terms = new ArrayList<String>();
				tokens = new ArrayList<String>();
				result = line.split(";");
				for (int i = 0; i < result.length; i++) {
					tokens.add(result[i]);
				}
				if (tokens.get(0).equals(query)) {
					annot.setIdQuery(tokens.get(0));
					annot.setType(tokens.get(tokens.size() - 2));
					annot.setConfidence(tokens.get(tokens.size() - 1));
					for (int j = 1; j < tokens.size() - 2; j++) {
						terms.add(tokens.get(j));
					}
					annot.setTerms(terms);

					annotation.add(annot);
				}
			}
			// for(int i=0;i<annotation.get(0).getVars().size();i++)
			// System.out.println(annotation.get(0).getVars().get(i));
			in.close();
			reader.close();

			f = new Feedback(query, annotation);
			// feedbackList.add(f);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return f;
	}

	/**
	 * Load feedback
	 * 
	 * @return
	 */
	public List<Feedback> loadFeedback() {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			Document doc;
			doc = db.parse(dir);
			Element root = doc.getDocumentElement();
			NodeList queries = root.getElementsByTagName("query");
			Element feedbackE = null;
			for (int i = 0; i < queries.getLength(); i++) {
				annotation = new Vector<Annotation>();
				Element query = (Element) queries.item(i);
				String idQuery = query.getAttributeNode("id").getValue();
				NodeList feedbackList = query.getElementsByTagName("feedback");
				NodeList listAnnotQuery = ((Element) feedbackList.item(0))
						.getElementsByTagName("annotation");

				for (int j = 0; j < listAnnotQuery.getLength(); j++) {
					Element annotE = (Element) listAnnotQuery.item(j);
					ArrayList<NodeList> annotArray = new ArrayList<NodeList>();
					annotArray.add(annotE.getElementsByTagName("subject"));
					annotArray.add(annotE.getElementsByTagName("predicate"));
					annotArray.add(annotE.getElementsByTagName("object"));
					annotArray.add(annotE.getElementsByTagName("evaluation"));
					annotArray.add(annotE.getElementsByTagName("confidence"));
					Annotation a = new Annotation();
					Triple triple = new Triple();
					for (int k = 0; k < annotArray.get(0).getLength(); k++) {
						triple.setSubject(annotArray.get(0).item(k)
								.getTextContent());
						triple.setPredicate(annotArray.get(1).item(k)
								.getTextContent());
						triple.setObject(annotArray.get(2).item(k)
								.getTextContent());
						a.setIdQuery(idQuery);
						a.setIdResult(idQuery);
						a.setTriple(triple);
						a.setType(annotArray.get(3).item(k).getTextContent());
						a.setConfidence(annotArray.get(4).item(k)
								.getTextContent());
						annotation.add(a);
					}
				}
				Feedback f = new Feedback(idQuery, annotation);
				this.feedbackList.add(f);
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return feedbackList;
	}

	/**
	 * build an annotation
	 * 
	 * @param element
	 * @return
	 */
	private Annotation createAnnotation(Element element) {
		// get list of the triples
		Annotation annotation = new Annotation();
		Triple triple = new Triple();
		NodeList tripleList = element.getElementsByTagName("triple");

		// get subject value of the triple
		NodeList subjectList = ((Element) tripleList.item(0))
				.getElementsByTagName("subject");
		Node noS = (Element) subjectList.item(0).getFirstChild();
		triple.setSubject(noS.getNodeValue());

		// get predicate value of the triple
		NodeList predicateList = ((Element) tripleList.item(0))
				.getElementsByTagName("predicate");
		Node noP = (Element) predicateList.item(0).getFirstChild();
		triple.setSubject(noP.getNodeValue());

		// get object value of the triple
		NodeList objectList = ((Element) tripleList.item(0))
				.getElementsByTagName("object");
		Node noO = (Element) objectList.item(0).getFirstChild();
		triple.setSubject(noO.getNodeValue());

		annotation.setTriple(triple);

		// get id query of the triple
		NodeList idQueryList = element.getElementsByTagName("idQuery");
		Node noIdQuery = (Element) idQueryList.item(0).getFirstChild();
		annotation.setIdQuery(noIdQuery.getNodeName());

		// get evaluation value of the triple
		NodeList evaluationList = element.getElementsByTagName("evaluation");
		Node noEval = (Element) evaluationList.item(0).getFirstChild();
		annotation.setType(noEval.getNodeValue());

		// get confidence value of the triple
		NodeList confidenceList = element.getElementsByTagName("confidence");
		Node noConf = (Element) confidenceList.item(0).getFirstChild();
		annotation.setConfidence(noConf.getNodeValue());

		return annotation;
	}

	public Triple createTriple(Element element) {
		Triple triple = new Triple();
		NodeList bindList = element.getElementsByTagName("binding");

		// set subject value
		NodeList subjectList = ((Element) bindList.item(0))
				.getElementsByTagName("uri");
		Node noS = (Element) subjectList.item(0).getFirstChild();
		triple.setSubject(noS.getNodeValue());

		// set predicate value
		NodeList predicateList = ((Element) bindList.item(1))
				.getElementsByTagName("uri");
		Node noP = (Element) predicateList.item(0).getFirstChild();
		triple.setPredicate(noP.getNodeValue());

		// set object (literal) value
		NodeList objectList = ((Element) bindList.item(2))
				.getElementsByTagName("literal");
		Node noO = (Element) objectList.item(0).getFirstChild();
		triple.setObject(noO.getNodeValue());

		return triple;
	}
}